/*******************************************************************/
/* @ All Rights Reserved Copyright (C) 2014 broada,Co.,Ltd.        */
/*                                                                 */
/*  NAME      = ora_packet.c                                       */
/*  NOTE      =                                                    */
/*  DATE      = 2014/09/26 by songbb                               */
/*******************************************************************/

#include <stdio.h>
#include <netinet/in.h>
#include <frct_comm.h>

#include "frcomm.h"
#include "frstr.h"
#include "frlog.h"

#include "../ora_core.h"

#include "../comm/ora_comm.h"
#include "../comm/ora_util.h"
#include "ora_tns_type.h"
#include "ora_packet.h"
#include "ora_datadescriptor.h"

/*******************************************************************************
*  FUNC     :  检测通用包头
*           :  *p_payload                           (数据内容)
*           :  ui_payload_len                       (数据长度)
*           :  *p_i_large_sdu_flag                  (是否是largeSDU的设置解析返回)
*  RTN      :  APM_L7_IS_YES                        (是Oracle协议)
*              APM_L7_IS_UNKNOWN                    (不能判断该协议)
*  NOTE     :
*******************************************************************************/
int ora_header_detect(char *p_payload
                    , unsigned int ui_payload_len
                    , int *p_i_large_sdu_flag)
{
    /*
     * XXX: 如果能确定当前的这个包是TCP三次握手后的第一次数据通信包，则肯定是客户端发起的connect请求，
     *      所以不符合检查要求的可以直接返回error; 否则的话有可能是长连接过程中的某一个oracle协议层的分片包，所以只能返回unknown。
     */

    unsigned short *p_us_pkt_len;
    unsigned int *p_ui_pkt_len;
    unsigned int ui_pkt_len;                    // packet length
    unsigned short *p_us_pkt_checksum;
    unsigned short us_pkt_checksum;             // packet checksum
    int i_tns_type;                             // tns type
    char c_options;                             // options
    unsigned short *p_us_header_checksum;
    unsigned short us_header_checksum;          // header checksum
    unsigned int *p_ui_pkt_len_supposed;
    unsigned int ui_pkt_len_supposed;           // 不确定包长字节的情况，4个字节的包长表示
    unsigned short *p_us_dataflag;
    unsigned short us_dataflag = 0;                 // data flag
    *p_i_large_sdu_flag = APM_ORA_FLAG_UNSET;

    if (ui_payload_len < APM_ORA_PKT_HEADER_LEN)
        goto unknown;

    p_us_pkt_len = (unsigned short *) p_payload;
    ui_pkt_len = ntohs(*p_us_pkt_len);

    p_us_pkt_checksum = (unsigned short *)(p_payload + 2);
    us_pkt_checksum = ntohs(*p_us_pkt_checksum);

    i_tns_type = *(p_payload + 4);

    c_options = *(p_payload + 5);

    p_us_header_checksum = (unsigned short *)(p_payload + 6);
    us_header_checksum = ntohs(*p_us_header_checksum);

    ui_pkt_len_supposed = 0;

    // XXX: 目前来看 header checksum一直为0x0000
    if (us_header_checksum != 0)
        goto unknown;

    if (ui_payload_len >= 10)
    {
        p_us_dataflag = (unsigned short *)(p_payload + 8);
        us_dataflag = ntohs(*p_us_dataflag);
    }

    // tns type类型只可能是1到18
    if (i_tns_type <= 0 || i_tns_type > 19)
        goto unknown;

    // 目前options位的值只可能为0或者第1,3,6位置1
    if (c_options != 0 && (c_options & (char) (~(0x01 | 0x04 | 0x20))) != 0)
        goto unknown;

    /*
     * tns_type 为 data(6)、marker(12)、未知(15)时，
     *   可以再检测一下是否使用largeSDU(oracle12c中传输数据包(APM_ORA_TNS_TYPE_DATA)时可能会使用largeSDU，即包头的开始4个字节表示包长，us_pkt_checksum被省略，并且是请求时，c_options的第3个bit位置1；而不是开始2个字节表示包长)
     *   APM_TNS_TYPE_DATA时，oracle对超过一定长度的数据会主动进行分包处理，但是实际的包长ui_len不一定等于分包后包头上表示的包长i_pkt_len
     */
    if (i_tns_type == APM_ORA_TNS_TYPE_DATA || i_tns_type == APM_ORA_TNS_TYPE_MARKER || i_tns_type == APM_ORA_TNS_TYPE_DATADESC)
    {
        if (ui_payload_len < APM_ORA_PKT_HEADER_LEN + APM_ORA_DATA_FLAG_LEN)
            goto unknown;
        // 如果在options中检测到largeSDU的标志位，则肯定是以4个字节表示包长
        if ((c_options & 0x20) == 1)
        {
            p_ui_pkt_len = (unsigned int *) p_payload;
            ui_pkt_len = (unsigned int) ntohl(*p_ui_pkt_len);
            *p_i_large_sdu_flag = FR_YES;
        }
        else
        {
            // 如果us_pkt_checksum不为0的话，那肯定是largeSDU
            if (us_pkt_checksum != 0)
            {
                p_ui_pkt_len = (unsigned int *) p_payload;
                ui_pkt_len = (unsigned int) ntohl(*p_ui_pkt_len);
                *p_i_large_sdu_flag = FR_YES;
            }
            else
            {
                // 不确定是否是largeSDU时，需要假设性的取一个前4个字节的pkt_len进行判断
                p_ui_pkt_len_supposed = (unsigned int *) p_payload;
                ui_pkt_len_supposed = (unsigned int) ntohl(*p_ui_pkt_len_supposed);

                if (ui_pkt_len == ui_payload_len)
                {
                    *p_i_large_sdu_flag = FR_NO;
                }
                else if (ui_pkt_len_supposed != 0)
                {
                    if (ui_pkt_len_supposed == ui_payload_len)
                    {
                        *p_i_large_sdu_flag = FR_YES;
                    }
                    else
                    {
                        // 未能识别到largeSDU的配置
//                        ORA_PRINT_WARN("can not tell large sdu setting.\n");
//                        ORA_FRLOG_ERROR("can not tell large sdu setting.");
                    }
                }
            }
        }

        // APM_TNS_TYPE_DATA时可能会分包，所以不能用包长判断
        if ((i_tns_type != APM_ORA_TNS_TYPE_DATA && i_tns_type != APM_ORA_TNS_TYPE_DATADESC && ui_pkt_len != ui_payload_len && ui_pkt_len_supposed != 0 && ui_pkt_len_supposed != ui_payload_len) ||
                (ui_pkt_len_supposed == 0 && ui_pkt_len < ui_payload_len) ||
                (ui_pkt_len_supposed != 0 && ui_pkt_len < ui_payload_len && ui_pkt_len_supposed < ui_payload_len))
            goto unknown;
    }
    else
    {
        if (us_pkt_checksum != 0 || ui_pkt_len != ui_payload_len)
            goto unknown;
    }

    // XXX: ui_pkt_len的默认最大阈值，8i中为4086，9i和10g中为32767，11g中为65535，12c中为2097152，此处使用的是12c的阈值，不知是否可以改进
    if (ui_pkt_len > APM_ORA_PKT_MAX_LEN
//        ui_pkt_len < ui_payload_len || // 分片包时会出现这种情况，所以这里已注释
//        (!(us_dataflag & 0x20) && ui_pkt_len != ui_payload_len && ui_pkt_len_supposed != 0 && (ui_pkt_len_supposed > APM_ORA_PKT_MAX_LEN || ui_pkt_len_supposed < ui_payload_len)) ||
//        ((us_dataflag & 0x20) && ui_pkt_len > ui_payload_len && ui_pkt_len_supposed != 0 && (ui_pkt_len_supposed > APM_ORA_PKT_MAX_LEN || ui_pkt_len_supposed < ui_payload_len))
    )
        goto unknown;

    return APM_L7_IS_YES;
unknown:
    return APM_L7_IS_UNKNOWN;
}

/*******************************************************************************
*  FUNC     :  解析通用包头
*  ARGS     :  *p_st_sess                           (Oracle私有的session)
*           :  *p_payload                           (数据内容)
*           :  ui_payload_len                       (数据长度)
*           :  *p_st_ora_header                     (通用头结构体)
*  RTN      :  0                                    (FR_SUCC)
*              1                                    (FR_FAIL)
*  NOTE     :
*******************************************************************************/
int ora_header_unpack(L7session_ora *p_st_sess
                    , char *p_payload
                    , unsigned int ui_payload_len
                    , Ora_header *p_st_ora_header)
{
    unsigned short *p_us_pkt_len;
    unsigned int *p_ui_pkt_len;
    unsigned int ui_pkt_len;                    // packet length
    int i_tns_type;                             // tns type
    char c_options;                             // options
    unsigned short *p_us_dataflag;
    unsigned short us_dataflag = 0;             // data flag
    int i_datalen = 0;

    p_us_pkt_len = (unsigned short *) p_payload;
    ui_pkt_len = ntohs(*p_us_pkt_len);

    i_tns_type = *(p_payload + 4);

    c_options = *(p_payload + 5);

    if (ui_payload_len >= 10)
    {
        p_us_dataflag = (unsigned short *)(p_payload + 8);
        us_dataflag = ntohs(*p_us_dataflag);
    }

    if (i_tns_type == APM_ORA_TNS_TYPE_DATA || i_tns_type == APM_ORA_TNS_TYPE_MARKER || i_tns_type == APM_ORA_TNS_TYPE_DATADESC)
    {
        if (p_st_sess->i_is_large_sdu == APM_ORA_FLAG_UNSET)
        {
            // largeSDU配置未知，不能进行数据解析
#if APM_ORA_DBG
            char arr_hex[8192] = {0x00};
            ora_bin_to_hex_string(p_payload, ui_payload_len, arr_hex, sizeof(arr_hex));
            ORA_PRINT_EMERG("can not tell large sdu setting:[%s].\n", arr_hex);
#endif
            goto error;
        }
        else if (p_st_sess->i_is_large_sdu == FR_YES)
        {
            p_ui_pkt_len = (unsigned int *) p_payload;
            ui_pkt_len = (unsigned int) ntohl(*p_ui_pkt_len);
        }
    }

    p_st_ora_header->ui_pkt_len = ui_pkt_len;
    p_st_ora_header->tns_type = (Ora_tns_type) i_tns_type;
    p_st_ora_header->c_options = c_options;
    p_st_ora_header->us_dataflag = us_dataflag;

    // 设置连接池标志
    p_st_sess->i_pool_enabled = p_st_ora_header->c_options & 0x1 ? 1 : 0;

    i_datalen = p_st_ora_header->ui_pkt_len - APM_ORA_PKT_HEADER_LEN - APM_ORA_DATA_FLAG_LEN - (p_st_sess->i_pool_enabled ? 16 : 0);

    if (p_st_ora_header->tns_type == APM_ORA_TNS_TYPE_DATA && i_datalen == 0)
        p_st_ora_header->tns_type = APM_ORA_TNS_TYPE_NULL;

    return FR_SUCC;
error:
    return FR_FAIL;
}

/*******************************************************************************
*  FUNC     :  初始化Oracle包的信息
*  ARGS     :  *p_st_ora_packet                     (Oracle数据包)
*  RTN      :  0                                    (FR_SUCC)
*              1                                    (FR_FAIL)
*  NOTE     :
*******************************************************************************/
int ora_init_ora_packet(L7_ora_packet *p_st_ora_packet)
{
    ORA_PRINT_INFO("init ora_packet...\n");
    if (p_st_ora_packet == NULL)
        return FR_SUCC;

    bytebuff_free(&(p_st_ora_packet->p_st_packet));
    if ((p_st_ora_packet->p_st_packet = bytebuff_creat()) == NULL)
        return FR_FAIL;
    p_st_ora_packet->tns_type = APM_ORA_TNS_TYPE_UNSET;
    p_st_ora_packet->ui_length_orig = 0;
    p_st_ora_packet->ui_len_to_read = 0;
    p_st_ora_packet->i_analyze_position = 0;
    p_st_ora_packet->i_is_first_packet = FR_YES;
    p_st_ora_packet->fragment_state = APM_ORA_FRAGMENT_INIT;
    p_st_ora_packet->i_is_request = APM_ORA_FLAG_UNSET;
    p_st_ora_packet->i_rpa_processed_flag = FR_NO;
    p_st_ora_packet->i_rxh_processed_flag = FR_NO;
    p_st_ora_packet->i_iov_processed_flag = FR_NO;
    ora_free((void **) &(p_st_ora_packet->p_payload_left));
    p_st_ora_packet->ui_payload_left_len = 0;
    p_st_ora_packet->ul_skip_len = 0L;
    p_st_ora_packet->i_need_next_packet_lob = FR_NO;

    return FR_SUCC;
}

/*******************************************************************************
*  FUNC     :  检查数据是否是分片包
*  ARGS     :  *p_st_sess                           (Oracle私有session)
*           :  *p_st_ora_packet                     (Oracle数据包)
*           :  i_is_request                         (是否是请求)
*           :  *p_data                              (数据内容)
*           :  ui_len                               (数据长度)
*           :  *p_ui_len_read                       (已读的数据长度)
*           :  *p_ui_len_to_read                    (需读的数据长度)
*           :  *p_ui_len_left                       (剩余的数据长度)
*  RTN      :  0                                    (是分片包)
*              1                                    (不是分片包)
*              2                                    (出错)
*  NOTE     :
*******************************************************************************/
FR_STATIC int __ora_pkt_is_fragmented(L7session_ora *p_st_sess
                                    , L7_ora_packet *p_st_ora_packet
                                    , int i_is_request
                                    , char *p_data
                                    , unsigned int ui_len
                                    , unsigned int *p_ui_len_read
                                    , unsigned int *p_ui_len_to_read
                                    , unsigned int *p_ui_len_left
                                    , Ora_tns_type *tns_type)
{
    Ora_header st_ora_header;
    memset(&st_ora_header, 0x00, sizeof(st_ora_header));
    int i_large_sdu_flag = 0;

    if (ora_header_detect(p_data, ui_len, &i_large_sdu_flag) != APM_L7_IS_YES) // 包头解析错误
        goto error;
    ora_sess_set_large_sdu_flag(p_st_sess, i_large_sdu_flag);

    if (ora_header_unpack(p_st_sess, p_data, ui_len, &st_ora_header) != FR_SUCC)
        goto error;

    ORA_PRINT_DBG("st_ora_header.ui_pkt_len:[%d]\n", st_ora_header.ui_pkt_len);
    *tns_type = st_ora_header.tns_type;
    if (p_st_ora_packet->tns_type == APM_ORA_TNS_TYPE_UNSET)
        p_st_ora_packet->tns_type = st_ora_header.tns_type;
    p_st_ora_packet->us_dataflag = st_ora_header.us_dataflag;
    if (ui_len < st_ora_header.ui_pkt_len)
    {
        *p_ui_len_to_read = st_ora_header.ui_pkt_len - ui_len;
        *p_ui_len_left = 0;
        *p_ui_len_read = ui_len;
        ORA_PRINT_INFO("__ora_pkt_is_fragmented test1 ui_len:[%d] st_ora_header.ui_pkt_len:[%d]\n", ui_len, st_ora_header.ui_pkt_len);
        goto fragmented;
    }
    else if (ui_len > st_ora_header.ui_pkt_len)
    {
        *p_ui_len_to_read = 0;
        *p_ui_len_left = ui_len - st_ora_header.ui_pkt_len;
        *p_ui_len_read = st_ora_header.ui_pkt_len;
        ORA_PRINT_INFO("__ora_pkt_is_fragmented test2 ui_len:[%d] st_ora_header.ui_pkt_len:[%d]\n", ui_len, st_ora_header.ui_pkt_len);
        goto fragmented;
    }
    else
    {
        *p_ui_len_to_read = 0;
        *p_ui_len_left = 0;
        *p_ui_len_read = ui_len;
    }

    if ((i_is_request && st_ora_header.tns_type == APM_ORA_TNS_TYPE_DATA && st_ora_header.us_dataflag & 0x20)
            || ui_len < st_ora_header.ui_pkt_len)
    {
        ORA_PRINT_INFO("__ora_pkt_is_fragmented test3\n");
        goto fragmented;
    }
    else
        goto not_fragmented;

fragmented:
    return APM_ORA_PACKET_FRAGMENTED;
not_fragmented:
    return APM_ORA_PACKET_UNFRAGMENTED;
error:
    return APM_ORA_PACKET_ERROR;
}

/*******************************************************************************
*  FUNC     :  检查分片包信息
*  ARGS     :  *p_st_sess                           (Oracle私有session)
*           :  i_is_request                         (是否是请求)
*           :  *p_payload                           (数据内容)
*           :  ui_payload_len                       (数据长度)
*           :  st_timestamp_first                   (分片包时，第一个分片包的时间；不为分片包时与st_timestamp_last相同)
*           :  *p_st_ora_packet                     (Oracle数据包)
*  RTN      :  0                                    (是分片包)
*              1                                    (不是分片包)
*              2                                    (出错)
*  NOTE     :
*******************************************************************************/
FR_STATIC int __ora_packet_check_fragment(L7session_ora *p_st_sess
                                        , int i_is_request
                                        , char *p_payload
                                        , unsigned int ui_payload_len
                                        , struct timeval st_timestamp
                                        , L7_ora_packet *p_st_ora_packet)
{
    int i_is_fragmented = 0;
    unsigned int ui_len_read = 0;       // 当前读了多少个字节
    unsigned int ui_len_to_read = 0;    // 还需要读多少个字节
    unsigned int ui_len_left = 0;       // 遗留了多少个字节
    Ora_tns_type tns_type = APM_ORA_TNS_TYPE_UNSET;

    p_st_ora_packet->i_is_request = i_is_request;

    i_is_fragmented = __ora_pkt_is_fragmented(p_st_sess, p_st_ora_packet, i_is_request, p_payload, ui_payload_len, &ui_len_read, &ui_len_to_read, &ui_len_left, &tns_type);
    ORA_PRINT_CRIT("i_is_fragmented:[%d] ui_len_read:[%d] ui_len_to_read:[%d] ui_len_left:[%d] tns_type:[%d]\n", i_is_fragmented, ui_len_read, ui_len_to_read, ui_len_left, tns_type);
    if (tns_type == APM_ORA_TNS_TYPE_DATADESC)
    {
        int i_lobd_len = 0;
        if (ora_datadescriptor_unpack(p_st_sess, p_payload, ui_len_read, &i_lobd_len) != FR_SUCC)
            goto error;

        ORA_PRINT_NOTICE("bytebuff_add 17 \n");
        if(ui_len_read <= APM_ORA_PKT_HEADER_LEN - APM_ORA_DATA_FLAG_LEN)
            goto error;
        if (bytebuff_add(p_st_ora_packet->p_st_packet
                , p_payload + APM_ORA_PKT_HEADER_LEN + APM_ORA_DATA_FLAG_LEN
                , ui_len_read - APM_ORA_PKT_HEADER_LEN - APM_ORA_DATA_FLAG_LEN) != FR_SUCC)
            goto error;

        p_st_ora_packet->ui_length_orig += ui_len_read;
        p_st_ora_packet->ui_len_to_read = ui_len_to_read;

        if (i_lobd_len > 0)
        {
            if ((unsigned int) i_lobd_len > ui_len_left)
            {
                ORA_PRINT_NOTICE("bytebuff_add 18\n");
                if (bytebuff_add(p_st_ora_packet->p_st_packet
                        , p_payload + ui_len_read
                        , ui_len_left) != FR_SUCC)
                    goto error;
                p_st_ora_packet->ul_skip_len = i_lobd_len - ui_len_left;
                p_st_ora_packet->ui_length_orig += ui_len_left;
                p_st_ora_packet->st_timestamp_last = st_timestamp;
                goto need_next_packet;
            }
            else
            {
                ORA_PRINT_NOTICE("bytebuff_add 19\n");
                if (bytebuff_add(p_st_ora_packet->p_st_packet
                        , p_payload + ui_len_read
                        , ui_len_left) != FR_SUCC)
                    goto error;
                p_st_ora_packet->ul_skip_len = 0L;
                p_st_ora_packet->ui_length_orig += ui_len_left;
                p_st_ora_packet->st_timestamp_last = st_timestamp;
                p_st_ora_packet->fragment_state = APM_ORA_FRAGMENT_INIT;
                goto success;
            }
        }
        else
        {
            if (ui_len_left > 0)
            {
                if (ui_len_left < APM_ORA_PKT_HEADER_LEN + APM_ORA_DATA_FLAG_LEN)
                {
                    p_st_ora_packet->p_payload_left = (char *) frmemdup(p_payload + ui_len_read, ui_len_left);
                    p_st_ora_packet->ui_payload_left_len = ui_len_left;
                }
                else
                    return __ora_packet_check_fragment(p_st_sess, i_is_request, p_payload + ui_len_read, ui_len_left, st_timestamp, p_st_ora_packet);
            }
            else
            {
                ora_free((void **) &(p_st_ora_packet->p_payload_left));
                p_st_ora_packet->ui_payload_left_len = 0;
            }
            p_st_ora_packet->fragment_state = i_is_request ? APM_ORA_FRAGMENT_NEED_NEXT_REQ_PACKET : APM_ORA_FRAGMENT_NEED_NEXT_RESP_PACKET;
            goto need_next_packet;
        }
    }
    if (i_is_fragmented == APM_ORA_PACKET_FRAGMENTED) // 是分片包
    {
        if (p_st_ora_packet->i_is_first_packet == FR_YES) // 是第一个包
        {
            p_st_ora_packet->i_is_first_packet = FR_NO;
            p_st_ora_packet->st_timestamp_first = st_timestamp;
            ORA_PRINT_NOTICE("bytebuff_add first fragmented packet\n");
            if (bytebuff_add(p_st_ora_packet->p_st_packet, p_payload, ui_len_read) != FR_SUCC)
                goto error;
        }
        else
        {
            ORA_PRINT_NOTICE("bytebuff_add 16 \n");
            if(ui_len_read <= APM_ORA_PKT_HEADER_LEN - APM_ORA_DATA_FLAG_LEN)
                goto error;
            if (bytebuff_add(p_st_ora_packet->p_st_packet
                    , p_payload + APM_ORA_PKT_HEADER_LEN + APM_ORA_DATA_FLAG_LEN
                    , ui_len_read - APM_ORA_PKT_HEADER_LEN - APM_ORA_DATA_FLAG_LEN) != FR_SUCC)
                goto error;
        }

        p_st_ora_packet->ui_length_orig += ui_len_read;
        p_st_ora_packet->ui_len_to_read = ui_len_to_read;

        if (ui_len_left > 0)
        {
            if (ui_len_left < APM_ORA_PKT_HEADER_LEN + APM_ORA_DATA_FLAG_LEN)
            {
                p_st_ora_packet->p_payload_left = (char *) frmemdup(p_payload + ui_len_read, ui_len_left);
                p_st_ora_packet->ui_payload_left_len = ui_len_left;
            }
            else
                return __ora_packet_check_fragment(p_st_sess, i_is_request, p_payload + ui_len_read, ui_len_left, st_timestamp, p_st_ora_packet);
        }
        else
        {
            ora_free((void **) &(p_st_ora_packet->p_payload_left));
            p_st_ora_packet->ui_payload_left_len = 0;
        }
        p_st_ora_packet->fragment_state = i_is_request ? APM_ORA_FRAGMENT_NEED_NEXT_REQ_PACKET : APM_ORA_FRAGMENT_NEED_NEXT_RESP_PACKET;
        goto need_next_packet;
    }
    else if (i_is_fragmented == APM_ORA_PACKET_UNFRAGMENTED) // 不是分片包
    {
        if (p_st_ora_packet->i_is_first_packet == FR_YES) // 是第一个包
        {
            p_st_ora_packet->i_is_first_packet = FR_NO;
            ORA_PRINT_NOTICE("bytebuff_add unfragmented packet\n");
            if (bytebuff_add(p_st_ora_packet->p_st_packet, p_payload, ui_payload_len) != FR_SUCC)
                goto error;
            p_st_ora_packet->st_timestamp_first = st_timestamp;
        }
        else // 如果不是第一个包，记下总包长，并去除后续包的前10个字节(包头+dataflag)加入到bytebuffer管理中
        {
            ORA_PRINT_NOTICE("bytebuff_add may last fragmented packet\n");
            if(ui_payload_len <= APM_ORA_PKT_HEADER_LEN + APM_ORA_DATA_FLAG_LEN)
                goto error;
            if (bytebuff_add(p_st_ora_packet->p_st_packet
                    , p_payload + APM_ORA_PKT_HEADER_LEN + APM_ORA_DATA_FLAG_LEN
                    , ui_payload_len - APM_ORA_PKT_HEADER_LEN - APM_ORA_DATA_FLAG_LEN) != FR_SUCC)
                goto error;
        }
        p_st_ora_packet->ui_length_orig += ui_payload_len;
        p_st_ora_packet->st_timestamp_last = st_timestamp;
        p_st_ora_packet->ui_len_to_read = 0;
        p_st_ora_packet->fragment_state = APM_ORA_FRAGMENT_INIT;
        ora_free((void **) &(p_st_ora_packet->p_payload_left));
        p_st_ora_packet->ui_payload_left_len = 0;
    }
    else
        goto error;

success:
    return APM_ORA_CHECK_FRAGMENT_SUCCESS;
need_next_packet:
    ORA_PRINT_WARN("NEED NEXT PACKET!\n");
    return APM_ORA_CHECK_FRAGMENT_NEED_NEXT_PACKET;
error:
    bytebuff_free(&(p_st_ora_packet->p_st_packet));
    ora_free((void **) &(p_st_ora_packet->p_payload_left));
    ORA_PRINT_WARN("error!\n");
    return APM_ORA_CHECK_FRAGMENT_ERROR;
}

/*******************************************************************************
*  FUNC     :  预备需要解析的数据
*  ARGS     :  *p_st_sess                           (Oracle私有的session)
*           :  *p_st_packet                        (协议分析入力数据)
*           :  *p_st_ora_packet                     (Oracle数据包)
*  RTN      :  0                                    (FR_SUCC)
*              1                                    (FR_FAIL)
*  NOTE     :
*******************************************************************************/
int ora_packet_prepare_data(L7session_ora *p_st_sess
                            , Apm_packet *p_st_packet
                            , L7_ora_packet *p_st_ora_packet)
{
    char *p_payload = NULL;
    unsigned int ui_payload_len = 0;
    int i_need_free_payload = FR_NO;
    int i_fun_ret;

    if (p_st_packet->i_direction == FR_DIRECT_UNKNOWN)
        goto error;

    p_payload = p_st_packet->p_payload;
    ui_payload_len = p_st_packet->ui_payload_len;

    if (p_st_packet->i_direction == FR_DIRECT_CLIENT2SRV) // 请求包
    {
        if (p_st_ora_packet->fragment_state == APM_ORA_FRAGMENT_NEED_NEXT_RESP_PACKET)
        {
            ora_core_add_unfinshed_fragmented_packets(p_st_sess);
            ORA_PRINT_EMERG("detect unfinshed response fragmented packet\n");
            ORA_PRINT_PACKET("unfinshed error packet", p_st_ora_packet);
            if (ora_init_ora_packet(p_st_ora_packet) != FR_SUCC)
                goto error;
        }
        if (p_st_ora_packet->fragment_state == APM_ORA_FRAGMENT_NEED_NEXT_REQ_PACKET)
        {
            if (p_st_ora_packet->ui_len_to_read > 0)
            {
                if (p_st_packet->ui_payload_len < p_st_ora_packet->ui_len_to_read)
                {
                    ORA_PRINT_NOTICE("bytebuff_add 4\n");
                    if (bytebuff_add(p_st_ora_packet->p_st_packet
                            , p_st_packet->p_payload
                            , p_st_packet->ui_payload_len) != FR_SUCC)
                        goto error;
                    p_st_ora_packet->ui_len_to_read -= p_st_packet->ui_payload_len;
                    p_st_ora_packet->ui_length_orig += p_st_packet->ui_payload_len;
                    p_st_ora_packet->st_timestamp_last = p_st_packet->st_timestamp;
                    goto need_next_packet;
                }
                else if (p_st_packet->ui_payload_len == p_st_ora_packet->ui_len_to_read)
                {
                    ORA_PRINT_NOTICE("bytebuff_add 5\n");
                    if (bytebuff_add(p_st_ora_packet->p_st_packet
                            , p_st_packet->p_payload
                            , p_st_packet->ui_payload_len) != FR_SUCC)
                        goto error;
                    p_st_ora_packet->ui_len_to_read = 0;
                    p_st_ora_packet->ui_length_orig += p_st_packet->ui_payload_len;
                    p_st_ora_packet->st_timestamp_last = p_st_packet->st_timestamp;
                    p_st_ora_packet->fragment_state = APM_ORA_FRAGMENT_INIT;
                    goto success;
                }
                else
                {
                    ORA_PRINT_NOTICE("bytebuff_add 6 p_st_ora_packet->ui_len_to_read:[%d]\n", p_st_ora_packet->ui_len_to_read);
                    if (bytebuff_add(p_st_ora_packet->p_st_packet
                            , p_st_packet->p_payload
                            , p_st_ora_packet->ui_len_to_read) != FR_SUCC)
                        goto error;
                    p_st_ora_packet->ui_length_orig += p_st_ora_packet->ui_len_to_read;
                    p_st_ora_packet->st_timestamp_last = p_st_packet->st_timestamp;
                    p_payload = p_st_packet->p_payload + p_st_ora_packet->ui_len_to_read;
                    ui_payload_len = p_st_packet->ui_payload_len - p_st_ora_packet->ui_len_to_read;
                    p_st_ora_packet->ui_len_to_read = 0;
                }
            }
            else if (p_st_ora_packet->ui_payload_left_len > 0 && p_st_ora_packet->p_payload_left != NULL)
            {
                if ((p_payload = (char *) frmalloc(sizeof(char) * (p_st_ora_packet->ui_payload_left_len + p_st_packet->ui_payload_len))) == NULL)
                {
                    ORA_MALLOCK_ERR;
                    goto error;
                }
                memcpy(p_payload, p_st_ora_packet->p_payload_left, p_st_ora_packet->ui_payload_left_len);
                memcpy(p_payload + p_st_ora_packet->ui_payload_left_len, p_st_packet->p_payload, p_st_packet->ui_payload_len);
                ui_payload_len = p_st_ora_packet->ui_payload_left_len + p_st_packet->ui_payload_len;
                i_need_free_payload = FR_YES;
            }
            else if (p_st_ora_packet->ul_skip_len > 0L)
            {
                if (p_st_ora_packet->ul_skip_len > p_st_packet->ui_payload_len)
                {
                    ORA_PRINT_NOTICE("bytebuff_add 7\n");
                    if (bytebuff_add(p_st_ora_packet->p_st_packet
                            , p_st_packet->p_payload
                            , p_st_packet->ui_payload_len) != FR_SUCC)
                        goto error;
                    p_st_ora_packet->ul_skip_len -= p_st_packet->ui_payload_len;
                    p_st_ora_packet->ui_length_orig += p_st_packet->ui_payload_len;
                    p_st_ora_packet->st_timestamp_last = p_st_packet->st_timestamp;
                    goto need_next_packet;
                }
                else if (p_st_ora_packet->ul_skip_len == p_st_packet->ui_payload_len)
                {
                    ORA_PRINT_NOTICE("bytebuff_add 8\n");
                    if (bytebuff_add(p_st_ora_packet->p_st_packet
                            , p_st_packet->p_payload
                            , p_st_packet->ui_payload_len) != FR_SUCC)
                        goto error;
                    p_st_ora_packet->ul_skip_len = 0L;
                    p_st_ora_packet->ui_length_orig += p_st_packet->ui_payload_len;
                    p_st_ora_packet->st_timestamp_last = p_st_packet->st_timestamp;
                    p_st_ora_packet->fragment_state = APM_ORA_FRAGMENT_INIT;
                    goto success;
                }
                else
                {
                    ORA_PRINT_NOTICE("bytebuff_add 9\n");
                    if (bytebuff_add(p_st_ora_packet->p_st_packet
                            , p_st_packet->p_payload
                            , p_st_ora_packet->ul_skip_len) != FR_SUCC)
                        goto error;
                    p_st_ora_packet->ul_skip_len = 0L;
                    p_st_ora_packet->ui_length_orig += p_st_ora_packet->ul_skip_len;
                    p_st_ora_packet->st_timestamp_last = p_st_packet->st_timestamp;
                    p_payload = p_st_packet->p_payload + p_st_ora_packet->ul_skip_len;
                    ui_payload_len = p_st_packet->ui_payload_len - p_st_ora_packet->ul_skip_len;
                }
            }
            else if (p_st_ora_packet->i_need_next_packet_lob == FR_YES)
            {
                ORA_PRINT_NOTICE("bytebuff_add 20\n");
                if (bytebuff_add(p_st_ora_packet->p_st_packet
                        , p_st_packet->p_payload
                        , p_st_packet->ui_payload_len) != FR_SUCC)
                    goto error;
                p_st_ora_packet->ul_skip_len = 0L;
                p_st_ora_packet->ui_length_orig += p_st_packet->ui_payload_len;
                p_st_ora_packet->st_timestamp_last = p_st_packet->st_timestamp;
                p_st_ora_packet->fragment_state = APM_ORA_FRAGMENT_INIT;
                goto success;
            }
        }
        else
        {
            if (ora_init_ora_packet(p_st_ora_packet) != FR_SUCC)
                goto error;
        }

        i_fun_ret = __ora_packet_check_fragment(p_st_sess, FR_YES, p_payload, ui_payload_len, p_st_packet->st_timestamp, p_st_ora_packet);
        if (i_need_free_payload)
            ora_free((void **) &p_payload);
        return i_fun_ret;
    }
    else if (p_st_packet->i_direction == FR_DIRECT_SRV2CLIENT) // 响应包
    {
        if (p_st_ora_packet->fragment_state == APM_ORA_FRAGMENT_NEED_NEXT_REQ_PACKET)
        {
            ora_core_add_unfinshed_fragmented_packets(p_st_sess);
            ORA_PRINT_EMERG("detect unfinshed request fragmented packet\n");
            ORA_PRINT_PACKET("unfinshed error packet", p_st_ora_packet);
            if (ora_init_ora_packet(p_st_ora_packet) != FR_SUCC)
                goto error;
        }
        if (p_st_ora_packet->fragment_state == APM_ORA_FRAGMENT_NEED_NEXT_RESP_PACKET)
        {
            if (p_st_ora_packet->ui_len_to_read > 0)
            {
                if (p_st_packet->ui_payload_len < p_st_ora_packet->ui_len_to_read)
                {
                    ORA_PRINT_NOTICE("bytebuff_add 10\n");
                    if (bytebuff_add(p_st_ora_packet->p_st_packet
                            , p_st_packet->p_payload
                            , p_st_packet->ui_payload_len) != FR_SUCC)
                        goto error;
                    p_st_ora_packet->ui_len_to_read -= p_st_packet->ui_payload_len;
                    p_st_ora_packet->ui_length_orig += p_st_packet->ui_payload_len;
                    p_st_ora_packet->st_timestamp_last = p_st_packet->st_timestamp;
                    goto need_next_packet;
                }
                else if (p_st_packet->ui_payload_len == p_st_ora_packet->ui_len_to_read)
                {
                    ORA_PRINT_NOTICE("bytebuff_add 11\n");
                    if (bytebuff_add(p_st_ora_packet->p_st_packet
                            , p_st_packet->p_payload
                            , p_st_packet->ui_payload_len) != FR_SUCC)
                        goto error;
                    p_st_ora_packet->ui_len_to_read = 0;
                    p_st_ora_packet->ui_length_orig += p_st_packet->ui_payload_len;
                    p_st_ora_packet->st_timestamp_last = p_st_packet->st_timestamp;
                    p_st_ora_packet->fragment_state = APM_ORA_FRAGMENT_INIT;
                    goto success;
                }
                else
                {
                    ORA_PRINT_NOTICE("bytebuff_add 12\n");
                    if (bytebuff_add(p_st_ora_packet->p_st_packet
                            , p_st_packet->p_payload
                            , p_st_ora_packet->ui_len_to_read) != FR_SUCC)
                        goto error;
                    p_st_ora_packet->ui_length_orig += p_st_ora_packet->ui_len_to_read;
                    p_st_ora_packet->st_timestamp_last = p_st_packet->st_timestamp;
                    p_payload = p_st_packet->p_payload + p_st_ora_packet->ui_len_to_read;
                    ui_payload_len = p_st_packet->ui_payload_len - p_st_ora_packet->ui_len_to_read;
                    p_st_ora_packet->ui_len_to_read = 0;
                }
            }
            else if (p_st_ora_packet->ui_payload_left_len > 0 && p_st_ora_packet->p_payload_left != NULL)
            {
                if ((p_payload = (char *) frmalloc(sizeof(char) * (p_st_ora_packet->ui_payload_left_len + p_st_packet->ui_payload_len))) == NULL)
                {
                    ORA_MALLOCK_ERR;
                    goto error;
                }
                memcpy(p_payload, p_st_ora_packet->p_payload_left, p_st_ora_packet->ui_payload_left_len);
                memcpy(p_payload + p_st_ora_packet->ui_payload_left_len, p_st_packet->p_payload, p_st_packet->ui_payload_len);
                ui_payload_len = p_st_ora_packet->ui_payload_left_len + p_st_packet->ui_payload_len;
                i_need_free_payload = FR_YES;
            }
            else if (p_st_ora_packet->ul_skip_len > 0L)
            {
                if (p_st_ora_packet->ul_skip_len > p_st_packet->ui_payload_len)
                {
                    ORA_PRINT_NOTICE("bytebuff_add 13\n");
                    if (bytebuff_add(p_st_ora_packet->p_st_packet
                            , p_st_packet->p_payload
                            , p_st_packet->ui_payload_len) != FR_SUCC)
                        goto error;
                    p_st_ora_packet->ul_skip_len -= p_st_packet->ui_payload_len;
                    p_st_ora_packet->ui_length_orig += p_st_packet->ui_payload_len;
                    p_st_ora_packet->st_timestamp_last = p_st_packet->st_timestamp;
                    goto need_next_packet;
                }
                else if (p_st_ora_packet->ul_skip_len == p_st_packet->ui_payload_len)
                {
                    ORA_PRINT_NOTICE("bytebuff_add 14\n");
                    if (bytebuff_add(p_st_ora_packet->p_st_packet
                            , p_st_packet->p_payload
                            , p_st_packet->ui_payload_len) != FR_SUCC)
                        goto error;
                    p_st_ora_packet->ul_skip_len = 0L;
                    p_st_ora_packet->ui_length_orig += p_st_packet->ui_payload_len;
                    p_st_ora_packet->st_timestamp_last = p_st_packet->st_timestamp;
                    p_st_ora_packet->fragment_state = APM_ORA_FRAGMENT_INIT;
                    goto success;
                }
                else
                {
                    ORA_PRINT_NOTICE("bytebuff_add 15\n");
                    if (bytebuff_add(p_st_ora_packet->p_st_packet
                            , p_st_packet->p_payload
                            , p_st_ora_packet->ul_skip_len) != FR_SUCC)
                        goto error;
                    p_st_ora_packet->ul_skip_len = 0L;
                    p_st_ora_packet->ui_length_orig += p_st_ora_packet->ul_skip_len;
                    p_st_ora_packet->st_timestamp_last = p_st_packet->st_timestamp;
                    p_payload = p_st_packet->p_payload + p_st_ora_packet->ul_skip_len;
                    ui_payload_len = p_st_packet->ui_payload_len - p_st_ora_packet->ul_skip_len;
                }
            }
            else if (p_st_ora_packet->i_need_next_packet_lob == FR_YES)
            {
                ORA_PRINT_NOTICE("bytebuff_add 21\n");
                if (bytebuff_add(p_st_ora_packet->p_st_packet
                        , p_st_packet->p_payload
                        , p_st_packet->ui_payload_len) != FR_SUCC)
                    goto error;
                p_st_ora_packet->ul_skip_len = 0L;
                p_st_ora_packet->ui_length_orig += p_st_packet->ui_payload_len;
                p_st_ora_packet->st_timestamp_last = p_st_packet->st_timestamp;
                p_st_ora_packet->fragment_state = APM_ORA_FRAGMENT_INIT;
                goto success;
            }
        }
        else
        {
            if (ora_init_ora_packet(p_st_ora_packet) != FR_SUCC)
                goto error;
        }

        i_fun_ret = __ora_packet_check_fragment(p_st_sess, FR_NO, p_payload, ui_payload_len, p_st_packet->st_timestamp, p_st_ora_packet);
        if (i_need_free_payload)
            ora_free((void **) &p_payload);
        return i_fun_ret;
    }

success:
    return APM_ORA_CHECK_FRAGMENT_SUCCESS;
need_next_packet:
    ORA_PRINT_WARN("NEED NEXT PACKET!\n");
    return APM_ORA_CHECK_FRAGMENT_NEED_NEXT_PACKET;
error:
    return APM_ORA_CHECK_FRAGMENT_ERROR;
}
